package com.xuecheng.manage_cms.service.impl;

import com.alibaba.fastjson.JSON;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.CmsSite;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.domain.cms.response.CmsCode;
import com.xuecheng.framework.domain.cms.response.CmsPageResult;
import com.xuecheng.framework.domain.cms.response.CmsPostPageResult;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.manage_cms.dao.CmsPageRepository;
import com.xuecheng.manage_cms.dao.CmsSiteRepository;
import com.xuecheng.manage_cms.mq.CmsPageMQ;
import com.xuecheng.manage_cms.service.CmsPageService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service
public class CmsPageServiceImpl implements CmsPageService {
    @Resource
    private CmsPageRepository cmsPageRepository;
    @Resource
    private CmsPageStaticHtmlUtil cmsPageStaticHtmlUtil;
    @Resource
    private CmsPageMQ cmsPageMQ;
    @Resource
    private CmsSiteRepository cmsSiteRepository;
    /**
     * 分页查询CmsPage
     *
     * @param page             从第一页开始，但是传递给dao必须-1，数据库第0页才算是第一页
     * @param size             每一页显示的个数
     * @param queryPageRequest 前台传过来的条件查询参数的实体类
     * @return 查询出的结果封装成统一返回对象
     */
    @Override
    public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) {
        // 防止queryPageRequest为null
        if (queryPageRequest == null) {
            queryPageRequest = new QueryPageRequest();
        }
        // 定义一个条件匹配器
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                // pageAliase包含某一个信息
                .withMatcher("pageAliase", ExampleMatcher.GenericPropertyMatchers.contains());
        // 条件值对象
        CmsPage cmsPage = new CmsPage();
        // 设置站点id作为条件
        if (StringUtils.isNotEmpty(queryPageRequest.getSiteId())) {
            cmsPage.setSiteId(queryPageRequest.getSiteId());
        }
        // 设置模板id作为条件
        if (StringUtils.isNotEmpty(queryPageRequest.getTemplateId())) {
            cmsPage.setTemplateId(queryPageRequest.getTemplateId());
        }
        // 设置页面别名作为条件
        if (StringUtils.isNotEmpty(queryPageRequest.getPageAliase())) {
            cmsPage.setPageAliase(queryPageRequest.getPageAliase());
        }

        // 创建条件查询对象
        Example<CmsPage> example = Example.of(cmsPage, exampleMatcher);

        // 分页的
        if (page <= 0) {
            page = 1;  // 用户从第一页开始
        }
        if (size <= 0 || size > 100) {
            size = 10;  // 一页不能显示太多
        }
        page = page - 1; //需要把第一页减一页传递给dao
        Pageable pageable = PageRequest.of(page, size); //封装Pageable
        // 最后查询
        Page<CmsPage> all = cmsPageRepository.findAll(example, pageable); //使用Pageable和Example查询数据

        QueryResult<CmsPage> queryResult = new QueryResult<>();    // 创建QueryResult来存放查询好的数据
        queryResult.setList(all.getContent());  // 存入数据列表
        queryResult.setTotal(all.getTotalElements()); // 存入数据总记录数
        return new QueryResponseResult(CommonCode.SUCCESS, queryResult); // 将上面的QueryResult和响应操作码二次封装返回
    }

    /**
     * 添加一个CmsPage
     *
     * @param cmsPage 前端传入CmsPage对象
     * @return CmsPageResult 返回新增的CmsPage和操作状态
     */
    @Override
    public CmsPageResult addCmsPage(CmsPage cmsPage) {
        if (cmsPage == null) {
            // 传入页面参数不合法 抛出异常
            ExceptionCast.cast(CmsCode.CMS_PAGE_DATA_IS_ILLEGAL);
        }
        // 校验页面名称,站点id,页面WebPath唯一性
        // 根据页面名称,站点id,页面WebPath去MongoDB的cms_page查询联合索引, 如果有,就说明存在了
        CmsPage result = cmsPageRepository.findByPageNameAndSiteIdAndAndPageWebPath(cmsPage.getPageName(), cmsPage.getSiteId(), cmsPage.getPageWebPath());
        if (result != null) {
            // 页面存在 抛出异常
            ExceptionCast.cast(CmsCode.CMS_PAGE_ALREADY_EXISTS);
        }
        // 新增页面
        cmsPage.setPageId(null);    //pageId是数据库自动生成,这里需要设置为null,让用户提交的无效
        cmsPage.setPageCreateTime(new Date());
        cmsPage.setPageUpdateTime(new Date());
        CmsPage saveCmsPage = cmsPageRepository.save(cmsPage);
        return new CmsPageResult(CommonCode.SUCCESS, saveCmsPage);
    }

    /**
     * 添加一个CmsPage,主要给课程管理预览的时候远程调用, 有则更新,没有就添加
     *
     * @param cmsPage 前端传入CmsPage对象
     * @return CmsPageResult 返回新增的CmsPage和操作状态
     */
    public CmsPageResult saveCmsPage(CmsPage cmsPage) {
        CmsPage one = cmsPageRepository.findByPageNameAndSiteIdAndAndPageWebPath(cmsPage.getPageName(), cmsPage.getSiteId(), cmsPage.getPageWebPath());
        if (one != null){
            // 页面存在了,需要更新
            return this.update(one.getPageId(),cmsPage);
        }else {
            return this.addCmsPage(cmsPage);
        }
    }

    /**
     * 根据页面Id查询一个CmsPge
     *
     * @param pageId 页面id
     * @return 一个CmsPage对象
     */
    @Override
    public CmsPage findById(String pageId) {
        if (StringUtils.isEmpty(pageId)) {
            ExceptionCast.cast(CmsCode.CMS_PAGE_DATA_IS_ILLEGAL);
        }
        // 单个对象会被封装到Optional
        Optional<CmsPage> optional = cmsPageRepository.findById(pageId);
        if (!optional.isPresent()) {
            // 没有查询到信息 抛出页面不存在异常
            ExceptionCast.cast(CmsCode.CMS_PAGE_DOES_NOT_EXIST);
        }
        return optional.get();
    }

    /**
     * 保存一个cmsPage
     *
     * @param cmsPage 需要保存的cmsPage
     * @return 保存过后的cmsPage
     */
    @Override
    public CmsPage save(CmsPage cmsPage) {
        return cmsPageRepository.save(cmsPage);
    }

    /**
     * 修改CmsPage页面
     *
     * @param id      CmsPage的ID
     * @param cmsPage 前台传入的CmsPage对象
     * @return 修改后的CmsPage和状态码
     */
    @Override
    public CmsPageResult update(String id, CmsPage cmsPage) {
        if (StringUtils.isEmpty(id) || cmsPage == null) {
            // 抛出页面信息不合法
            ExceptionCast.cast(CmsCode.CMS_PAGE_DATA_IS_ILLEGAL);
        }
        // 先查出数据
        CmsPage one = this.findById(id);
        if (one == null) {
            // 查不到页面数据 无法修改  抛出异常
            ExceptionCast.cast(CmsCode.CMS_PAGE_DOES_NOT_EXIST);
        }
        // 更新数据
        one.setSiteId(cmsPage.getSiteId());
        one.setPageWebPath(cmsPage.getPageWebPath());
        one.setPagePhysicalPath(cmsPage.getPagePhysicalPath());
        one.setPageAliase(cmsPage.getPageAliase());
        one.setPageName(cmsPage.getPageName());
        one.setTemplateId(cmsPage.getTemplateId());
        one.setPageType(cmsPage.getPageType());
        one.setDataUrl(cmsPage.getDataUrl());
        one.setPageUpdateTime(new Date());
        CmsPage save = cmsPageRepository.save(one);
        return new CmsPageResult(CommonCode.SUCCESS, save);
    }


    /**
     * 根据id删除CmsPage
     *
     * @param pageId 前台传递CmsPage的id
     * @return 响应结果
     */
    @Override
    public ResponseResult delete(String pageId) {
        if (StringUtils.isEmpty(pageId)) {
            // 数据不合法
            ExceptionCast.cast(CmsCode.CMS_PAGE_DATA_IS_ILLEGAL);
        }
        // 先查询有没有
        Optional<CmsPage> optional = cmsPageRepository.findById(pageId);
        if (!optional.isPresent()) {
            // 如果没有根据id查找到数据,抛出不存在
            ExceptionCast.cast(CmsCode.CMS_PAGE_DOES_NOT_EXIST);
        }
        cmsPageRepository.deleteById(pageId);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
     * 页面静态化方法
     *
     * @return 返回页面静态化后字符串
     */
    public String getPageHtml(String pageId) {
        // 获取数据模型
        Map model = cmsPageStaticHtmlUtil.getModelByPageId(pageId);
        if (model == null) {
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAURLISNULL);
        }
        // 获取模板
        String templateContent = cmsPageStaticHtmlUtil.getTemplateByPageId(pageId);
        if (StringUtils.isEmpty(pageId)) {
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
        }
        // 执行静态化
        String html = cmsPageStaticHtmlUtil.generateHtml(templateContent, model);
        return html;
    }

    /**
     * 页面发布接口
     *
     * @param pageId 页面id
     * @return 响应
     */
    @Override
    public ResponseResult postPage(String pageId) {
        // 执行页面静态化
        String pageHtml = this.getPageHtml(pageId);
        // 将静态化文件存储到GridFS中
        CmsPage cmsPage = cmsPageStaticHtmlUtil.saveHtml(pageId, pageHtml);
        // 向MQ发消息
        cmsPageMQ.sendPostPage(cmsPage);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
     * 一键发布Cms页面,给课程发布的时候调用调用
     *
     * @param cmsPage 需要发布的页面
     */
    @Override
    public CmsPostPageResult postPageQuick(CmsPage cmsPage) {
        // 将页面信息存储到cms_page集合中 传递给页面静态化
        CmsPageResult cmsPageResult = this.saveCmsPage(cmsPage);
        if (!cmsPageResult.isSuccess()){
            ExceptionCast.cast(CommonCode.FAIL);
        }
        CmsPage one = cmsPageResult.getCmsPage();
        // 执行页面静态化
        // 得到页面id
        String pageId = one.getPageId();
        // 页面发布
        this.postPage(pageId);
        // 拼接Url生成最后的真实访问路径
        // 得到站点id
        Optional<CmsSite> optional = cmsSiteRepository.findById(cmsPage.getSiteId());
        if (!optional.isPresent()) {
            ExceptionCast.cast(CommonCode.FAIL);
        }
        CmsSite cmsSite = optional.get();
        String url = cmsSite.getSiteDomain()+cmsSite.getSiteWebPath()+cmsPage.getPageWebPath()+cmsPage.getPageName();
        return new CmsPostPageResult(CommonCode.SUCCESS,url);
    }
}
